/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { TestBase } from '../../pages/testbase';
import { common2D } from '@kit.ArkGraphics2D';
import { drawing } from '@kit.ArkGraphics2D';
import { OHRandom } from '../../utils/OHRandom';

enum PenAllFunction {
  SET_MITER_LIMIT = 0,
  GET_MITER_LIMIT,
  SET_SHADER_EFFECT,
  GET_COLOR,
  SET_COLOR,
  SET_STROKE_WIDTH,
  GET_WIDTH,
  SET_ANTI_ALIAS,
  IS_ANTI_ALIAS,
  SET_ALPHA,
  GET_ALPHA,
  SET_COLOR_FILTER,
  GET_COLOR_FILTER,
  SET_IMAGE_FILTER,
  SET_MASK_FILTER,
  SET_PATH_EFFECT,
  SET_SHADOW_LAYER,
  SET_BLEND_MODE,
  SET_DITHER,
  SET_JOIN_STYLE,
  GET_JOIN_STYLE,
  SET_CAP_STYLE,
  GET_CAP_STYLE,
  RESET,
  GET_FILL_PATH,
  MAX
}

enum PenOperationFunction {
  GET_MITER_LIMIT = 0,
  GET_COLOR,
  GET_WIDTH,
  IS_ANTI_ALIAS,
  GET_ALPHA,
  GET_COLOR_FILTER,
  GET_JOIN_STYLE,
  GET_CAP_STYLE,
  RESET,
  GET_FILL_PATH,
  MAX
}

export class StabilityPenNew extends TestBase {
  /*
  @CaseID:SUB_BASIC_GRAPHICS_SPECIAL_STABLE_TS_DRAWING_PEN_0100
  @Description:Pen new-置空循环
  @Step:
  1、运行脚本，循环执行hidumper命令查询内存
  2、执行自动化用例：pen new-置空，循环调用1000次
  3、执行结束后等待3分钟
  4、结束脚本运行，抓取的内存值转成折线图，观察内存变化
  @Result:
  1、程序运行正常，无crash
  2、内存平稳，没有持续增长，执行后内存回落到执行前；
  */
  public async OnTestStability(canvas: drawing.Canvas) {
    console.log("StabilityPenNew OnTestStability");
    for (let i = 0; i < this.testCount_; i++) {
      let pen = new drawing.Pen();
      let pen1 = new drawing.Pen(pen);
    }
  }
}

export class StabilityPenInvoke extends TestBase {
  private colorFilter: drawing.ColorFilter = null;
  private imageFilter: drawing.ImageFilter = null;
  private maskFilter: drawing.MaskFilter = null;
  private shadowLayer: drawing.ShadowLayer = null;
  private colorShader: drawing.ShaderEffect = null;
  private pathEffect: drawing.PathEffect = null;
  private pathSrc: drawing.Path = null;
  private pathDst: drawing.Path = null;
  private gradientEffect: drawing.ShaderEffect = null;
  private gradientEffect2: drawing.ShaderEffect = null;
  private gradientEffect3: drawing.ShaderEffect = null;

  static functions_: Map<PenAllFunction, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => void> = new Map([
    [PenAllFunction.SET_MITER_LIMIT, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetMiterLimitTest(pen)
    }],
    [PenAllFunction.GET_MITER_LIMIT, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenGetMiterLimitTest(pen)
    }],
    [PenAllFunction.SET_SHADER_EFFECT, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetShaderEffectTest(pen)
    }],
    [PenAllFunction.GET_COLOR, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenGetColorTest(pen)
    }],
    [PenAllFunction.SET_COLOR, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetColorTest(pen)
    }],
    [PenAllFunction.SET_STROKE_WIDTH, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetStrokeWidthTest(pen)
    }],
    [PenAllFunction.GET_WIDTH, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenGetWidthTest(pen)
    }],
    [PenAllFunction.SET_ANTI_ALIAS, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetAntiAliasTest(pen)
    }],
    [PenAllFunction.IS_ANTI_ALIAS, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenIsAntiAliasTest(pen)
    }],
    [PenAllFunction.SET_ALPHA, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetAlphaTest(pen)
    }],
    [PenAllFunction.GET_ALPHA, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenGetAlphaTest(pen)
    }],
    [PenAllFunction.SET_COLOR_FILTER, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetColorFilterTest(pen)
    }],
    [PenAllFunction.GET_COLOR_FILTER, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenGetColorFilterTest(pen)
    }],
    [PenAllFunction.SET_IMAGE_FILTER, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetImageFilterTest(pen)
    }],
    [PenAllFunction.SET_MASK_FILTER, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetMaskFilterTest(pen)
    }],
    [PenAllFunction.SET_PATH_EFFECT, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetPathEffectTest(pen)
    }],
    [PenAllFunction.SET_SHADOW_LAYER, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetShadowLayerTest(pen)
    }],
    [PenAllFunction.SET_BLEND_MODE, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetBlendModeTest(pen)
    }],
    [PenAllFunction.SET_DITHER, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetDitherTest(pen)
    }],
    [PenAllFunction.SET_JOIN_STYLE, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetJoinStyleTest(pen)
    }],
    [PenAllFunction.GET_JOIN_STYLE, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenGetJoinStyleTest(pen)
    }],
    [PenAllFunction.SET_CAP_STYLE, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenSetCapStyleTest(pen)
    }],
    [PenAllFunction.GET_CAP_STYLE, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenGetCapStyleTest(pen)
    }],
    [PenAllFunction.RESET, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenResetTest(pen)
    }],
    [PenAllFunction.GET_FILL_PATH, (penInvoke: StabilityPenInvoke, pen: drawing.Pen) => {
      penInvoke.PenGetFillPathTest(pen)
    }],
  ]);

  /*
  @CaseID:SUB_BASIC_GRAPHICS_SPECIAL_STABLE_TS_DRAWING_PEN_0200
  @Description:Pen new-相关接口全调用-置空循环
  @Step:
  1、运行脚本，循环执行hidumper命令查询内存
  2、执行自动化用例：new pen-相关接口全调用-置空，循环调用1000次
  3、执行结束后等待3分钟
  4、结束脚本运行，抓取的内存值转成折线图，观察内存变化"
  @Result:
  1、程序运行正常，无crash
  2、内存平稳，没有持续增长，执行后内存回落到执行前；
  */
  public async OnTestStability(canvas: drawing.Canvas) {
    console.log("StabilityPenInvoke OnTestStability");
    this.colorFilter = drawing.ColorFilter.createBlendModeColorFilter({
      alpha: OHRandom.GetRandomNum(0, 0xFF),
      red: OHRandom.GetRandomNum(0, 0xFF),
      green: OHRandom.GetRandomNum(0, 0xFF),
      blue: OHRandom.GetRandomNum(0, 0xFF)
    }, OHRandom.GetRandomNum(0, 0xFF) % (drawing.BlendMode.LUMINOSITY + 1));
    this.imageFilter = drawing.ImageFilter.createFromColorFilter(this.colorFilter);
    this.maskFilter =
      drawing.MaskFilter.createBlurMaskFilter(OHRandom.GetRandomNum(0, drawing.BlurType.INNER),
        OHRandom.GetRandomNum(1, 0xFFFFFFFF));
    this.pathEffect =
      drawing.PathEffect.createDashPathEffect([OHRandom.GetRandomNum(1, 30), OHRandom.GetRandomNum(1, 10)],
        OHRandom.GetRandomNum(1, 0xFFFFFFFF));
    let min = Math.min(this.width_, this.height_);
    this.shadowLayer =
      drawing.ShadowLayer.create(OHRandom.GetRandomNum(1, min / 2), OHRandom.GetRandomNum(0, this.width_),
        OHRandom.GetRandomNum(0, this.height_), {
        alpha: OHRandom.GetRandomNum(0, 0xFF),
        red: OHRandom.GetRandomNum(0, 0xFF),
        green: OHRandom.GetRandomNum(0, 0xFF),
        blue: OHRandom.GetRandomNum(0, 0xFF)
      });
    this.pathSrc = new drawing.Path();
    this.pathDst = new drawing.Path();
    this.pathSrc.arcTo(100, 100, 200, 200, 0, 45);
    this.pathDst.arcTo(200, 200, 300, 300, 0, 90);
    this.colorShader = drawing.ShaderEffect.createColorShader(0xFF00FF00);
    this.gradientEffect = this.CreateConicalGradientEffect();
    this.gradientEffect2 = this.CreateGradientEffect();
    this.gradientEffect3 = this.CreateSweepGradientEffect();

    for (let i = 0; i < this.testCount_; i++) {
      let pen = new drawing.Pen();
      for (let j = 0; j < PenAllFunction.MAX; j++) {
        StabilityPenInvoke.functions_.get(j)(this, pen);
      }
    }
  }

  PenSetMiterLimitTest(pen: drawing.Pen) {
    pen.setMiterLimit(OHRandom.GetRandomNum(0, 10));
  }

  PenGetMiterLimitTest(pen: drawing.Pen) {
    pen.getMiterLimit();
  }

  CreateGradientEffect(): drawing.ShaderEffect {
    const colors2 = [0xFF0000FF, 0xFFFF0000];
    const centerPoint2: common2D.Point =
      { x: OHRandom.GetRandomNum(0, this.width_), y: OHRandom.GetRandomNum(0, this.height_) };
    const radius2 = OHRandom.GetRandomNum(0, this.width_ / 2);
    const tileMode2 = drawing.TileMode.REPEAT;
    const positions2 = [0.0, 1.0];
    const gradientEffect2 = drawing.ShaderEffect.createRadialGradient(
      centerPoint2,
      radius2,
      colors2,
      tileMode2,
      positions2,
      null
    );
    return gradientEffect2
  }

  CreateSweepGradientEffect(): drawing.ShaderEffect {
    const colors3 = [0xFF0000FF, 0xFFFF0000];
    const centerPoint3: common2D.Point =
      { x: OHRandom.GetRandomNum(0, this.width_), y: OHRandom.GetRandomNum(0, this.height_) };
    const tileMode3 = drawing.TileMode.REPEAT;
    const startAngle = OHRandom.GetRandomNum(0, 360);
    const endAngle = OHRandom.GetRandomNum(0, 360);
    const positions3 = [0.0, 1.0];
    const gradientEffect3 = drawing.ShaderEffect.createSweepGradient(
      centerPoint3,
      colors3,
      tileMode3,
      startAngle,
      endAngle,
      positions3,
      null
    );
    return gradientEffect3;
  }

  CreateConicalGradientEffect(): drawing.ShaderEffect {
    const startPoint: common2D.Point =
      { x: OHRandom.GetRandomNum(0, this.width_), y: OHRandom.GetRandomNum(0, this.height_) };
    const startRadius = OHRandom.GetRandomNum(0, 360);
    const endPoint: common2D.Point =
      { x: OHRandom.GetRandomNum(0, this.width_), y: OHRandom.GetRandomNum(0, this.height_) };
    const endRadius = OHRandom.GetRandomNum(0, 360);
    const colors = [0xFF0000FF, 0xFFFF0000];
    const tileMode = drawing.TileMode.CLAMP;
    const positions = [0.0, 1.0];
    const gradientEffect = drawing.ShaderEffect.createConicalGradient(
      startPoint,
      startRadius,
      endPoint,
      endRadius,
      colors,
      tileMode,
      positions,
      null
    );
    return gradientEffect;
  }

  PenSetShaderEffectTest(pen: drawing.Pen) {
    //1.创建具有单一颜色的着色器
    pen.setShaderEffect(this.colorShader);
    //2.创建着色器，在给定圆心和半径的情况下生成径向渐变。 从起点到终点颜色从内到外进行圆形渐变（从中间向外拉）被称为径向渐变。
    pen.setShaderEffect(this.gradientEffect2);
    //3.createSweepGradient
    pen.setShaderEffect(this.gradientEffect3);
    //4.createConicalGradient创建着色器，在给定两个圆之间生成渐变。
    pen.setShaderEffect(this.gradientEffect);
  }

  PenGetColorTest(pen: drawing.Pen) {
    pen.getColor();
  }

  PenSetColorTest(pen: drawing.Pen) {
    pen.setColor({
      alpha: OHRandom.GetRandomNum(0, 0xFF),
      red: OHRandom.GetRandomNum(0, 0xFF),
      green: OHRandom.GetRandomNum(0, 0xFF),
      blue: OHRandom.GetRandomNum(0, 0xFF)
    });
    // todo: setColor(color: number): void;此方法还未转测
    // pen.setColor(OHRandom.GetRandomNum(0, 0xFF), OHRandom.GetRandomNum(0, 0xFF),
    //   OHRandom.GetRandomNum(0, 0xFF), OHRandom.GetRandomNum(0, 0xFF));
  }

  PenSetStrokeWidthTest(pen: drawing.Pen) {
    pen.setStrokeWidth(OHRandom.GetRandomNum(1, 50));
  }

  PenGetWidthTest(pen: drawing.Pen) {
    pen.getWidth();
  }

  PenSetAntiAliasTest(pen: drawing.Pen) {
    pen.setAntiAlias(OHRandom.GetRandomNum(0, 1) % 2 == 0);
  }

  PenIsAntiAliasTest(pen: drawing.Pen) {
    pen.isAntiAlias();
  }

  PenSetAlphaTest(pen: drawing.Pen) {
    pen.setAlpha(OHRandom.GetRandomNum(0, 255));
  }

  PenGetAlphaTest(pen: drawing.Pen) {
    pen.getAlpha();
  }

  PenSetColorFilterTest(pen: drawing.Pen) {
    pen.setColorFilter(this.colorFilter);
  }

  PenGetColorFilterTest(pen: drawing.Pen) {
    pen.getColorFilter();
  }

  PenSetImageFilterTest(pen: drawing.Pen) {
    pen.setImageFilter(this.imageFilter);
  }

  PenSetMaskFilterTest(pen: drawing.Pen) {
    pen.setMaskFilter(this.maskFilter);
  }

  PenSetPathEffectTest(pen: drawing.Pen) {
    pen.setPathEffect(this.pathEffect);
  }

  PenSetShadowLayerTest(pen: drawing.Pen) {
    pen.setShadowLayer(this.shadowLayer);
  }

  PenSetBlendModeTest(pen: drawing.Pen) {
    pen.setBlendMode(OHRandom.GetRandomNum(0, drawing.BlendMode.SRC));
  }

  PenSetDitherTest(pen: drawing.Pen) {
    pen.setDither(OHRandom.GetRandomNum(0, 1) % 2 == 0);
  }

  PenSetJoinStyleTest(pen: drawing.Pen) {
    pen.setJoinStyle(OHRandom.GetRandomNum(0, drawing.JoinStyle.ROUND_JOIN));
  }

  PenGetJoinStyleTest(pen: drawing.Pen) {
    pen.getJoinStyle();
  }

  PenSetCapStyleTest(pen: drawing.Pen) {
    pen.setCapStyle(OHRandom.GetRandomNum(0, drawing.CapStyle.SQUARE_CAP));
  }

  PenGetCapStyleTest(pen: drawing.Pen) {
    pen.getCapStyle();
  }

  PenResetTest(pen: drawing.Pen) {
    pen.reset();
  }

  PenGetFillPathTest(pen: drawing.Pen) {
    pen.getFillPath(this.pathSrc, this.pathDst);
  }
}

export class StabilityPenRandInvoke extends TestBase {

  private pathSrc: drawing.Path = null;
  private pathDst: drawing.Path = null;

  static functions_: Map<PenOperationFunction, (penRandInvoke: StabilityPenRandInvoke, pen: drawing.Pen) => void> = new Map([
    [PenOperationFunction.GET_MITER_LIMIT, (penRandInvoke: StabilityPenRandInvoke, pen: drawing.Pen) => {
      penRandInvoke.PenGetMiterLimitTest(pen)
    }],
    [PenOperationFunction.GET_COLOR, (penRandInvoke: StabilityPenRandInvoke, pen: drawing.Pen) => {
      penRandInvoke.PenGetColorTest(pen)
    }],
    [PenOperationFunction.GET_WIDTH, (penRandInvoke: StabilityPenRandInvoke, pen: drawing.Pen) => {
      penRandInvoke.PenGetWidthTest(pen)
    }],
    [PenOperationFunction.IS_ANTI_ALIAS, (penRandInvoke: StabilityPenRandInvoke, pen: drawing.Pen) => {
      penRandInvoke.PenIsAntiAliasTest(pen)
    }],
    [PenOperationFunction.GET_ALPHA, (penRandInvoke: StabilityPenRandInvoke, pen: drawing.Pen) => {
      penRandInvoke.PenGetAlphaTest(pen)
    }],
    [PenOperationFunction.GET_COLOR_FILTER, (penRandInvoke: StabilityPenRandInvoke, pen: drawing.Pen) => {
      penRandInvoke.PenGetColorFilterTest(pen)
    }],
    [PenOperationFunction.GET_JOIN_STYLE, (penRandInvoke: StabilityPenRandInvoke, pen: drawing.Pen) => {
      penRandInvoke.PenGetJoinStyleTest(pen)
    }],
    [PenOperationFunction.GET_CAP_STYLE, (penRandInvoke: StabilityPenRandInvoke, pen: drawing.Pen) => {
      penRandInvoke.PenGetCapStyleTest(pen)
    }],
    [PenOperationFunction.RESET, (penRandInvoke: StabilityPenRandInvoke, pen: drawing.Pen) => {
      penRandInvoke.PenResetTest(pen)
    }],
    [PenOperationFunction.GET_FILL_PATH, (penRandInvoke: StabilityPenRandInvoke, pen: drawing.Pen) => {
      penRandInvoke.PenGetFillPathTest(pen)
    }],
  ]);

  /*
    @CaseID:SUB_BASIC_GRAPHICS_SPECIAL_STABLE_TS_DRAWING_PEN_0300
    @Description:Pen相关操作接口随机循环调用
    @Step:
    1、运行脚本，循环执行hidumper命令查询内存
    2、执行自动化用例：
    new pen
    pen相关操作接口调用，循环调用1000次
    pen置空
    3、执行结束后等待3分钟
    4、结束脚本运行，抓取的内存值转成折线图，观察内存变化"
    @Result:
        1、程序运行正常，无crash
        2、内存平稳，没有持续增长，执行后内存回落到执行前；
  */
  public async OnTestStability(canvas: drawing.Canvas) {
    console.log("StabilityPenRandInvoke OnTestStability");
    let pen = new drawing.Pen();
    this.pathSrc = new drawing.Path();
    this.pathDst = new drawing.Path();
    this.pathSrc.arcTo(100, 100, 200, 200, 0, 45);
    this.pathDst.arcTo(200, 200, 300, 300, 0, 90);
    for (let i = 0; i < this.testCount_; i++) {
      StabilityPenRandInvoke.functions_.get(OHRandom.GetRandomNum(0, PenOperationFunction.MAX - 1))(this, pen);
    }
  }

  PenGetMiterLimitTest(pen: drawing.Pen) {
    pen.getMiterLimit();
  }

  PenGetColorTest(pen: drawing.Pen) {
    pen.getColor();
  }

  PenGetWidthTest(pen: drawing.Pen) {
    pen.getWidth();
  }

  PenIsAntiAliasTest(pen: drawing.Pen) {
    pen.isAntiAlias();
  }

  PenGetAlphaTest(pen: drawing.Pen) {
    pen.getAlpha();
  }

  PenGetColorFilterTest(pen: drawing.Pen) {
    pen.getColorFilter();
  }

  PenGetJoinStyleTest(pen: drawing.Pen) {
    pen.getJoinStyle();
  }

  PenGetCapStyleTest(pen: drawing.Pen) {
    pen.getCapStyle();
  }

  PenResetTest(pen: drawing.Pen) {
    pen.reset();
  }

  PenGetFillPathTest(pen: drawing.Pen) {
    pen.getFillPath(this.pathSrc, this.pathDst);
  }
}